﻿; (function () {
    if (!window.$axscreenshot) window.$axscreenshot = {};

    /**
     * When the script is fully loaded, pull up the style file
     **/
    $(document).ready(function () {
        $('<link>').appendTo('head').attr({
            rel: 'stylesheet',
            type: 'text/css',
            href: '/Content/plugins/axScreenshot/styles/axScreenshot9.css'
        });

        $axure.utils.loadJS('/Scripts/plugins/feedback/axImgAreaSelect.js');
    });

    /* axScreenshot Messages */
    var axureCheck = "isAxure";
    var axureCheckFor9 = "isAxure9";
    var axureCheckResponse = "yesIAmAxure";
    var axureCheckResponseAgain = "okContinueAxure";
    var axureTakeScreenshot = "axTakeScreenshot";
    var axureShouldTakeScreenshot = "youShouldTakeAScreenshot";     // Keyboard message

    /* Extention links */
    $axscreenshot.chromeLink = '\'https:\/\/chrome.google.com\/webstore\/detail\/axure-share-extension-for\/fiidicpfcmmoobdpadllfjklbdegfjaf?hl=en\'';
    $axscreenshot.chromiumEdgeLink = "'https://microsoftedge.microsoft.com/addons/detail/miagpbdmihkgmbgllleikgfdgbbgblch'";

    var tempCount = 0;                      // Number of screenshots taken (temporary id)
    var $currFeedbackEntry = null;          // Current element (Issue/Comment) user is on (used for attaching the screenshot on mouse)
    var $currFeedbackEntry_keyboard = null; // Current element (Issue/Comment user is on (used for attaching the screenshot via keyboard)

    var isScreenshotSetup = true;
    var isRequestingScreenshot = false;
    var isExtensionAttached = false;

    var cropTool = null;
    var $targetPanel = null;
    var $parentContainer = null;
    var $clearOnClickObjs = null;
    var feedbackContainerClasses = null;
    var issueContainers = null;
    var commentContainers = null;

    var postScreenshotCallback = null;

    /* axScreenshot State Management */
    $axscreenshot.axScreenshotJsAvailable = true;
    var isWindows = navigator.appVersion.indexOf("Win") != -1;
    var isMac = navigator.appVersion.indexOf("Mac") != -1;
    $axscreenshot.isChrome = window.chrome != null && window.navigator.vendor === "Google Inc.";
    $axscreenshot.isChromiumEdge = $axscreenshot.isChrome && window.navigator.userAgent.indexOf("Edg") != -1;
    $axscreenshot.isFirefox = typeof InstallTrigger !== 'undefined';
    $axscreenshot.isIE8 = document.documentMode == 8 && window.msPerformance == null;
    $axscreenshot.isIE9 = document.documentMode == 9 && window.msPerformance != null;
    $axscreenshot.isIE10 = document.documentMode == 10;
    $axscreenshot.isScreenshotCompatible = $axscreenshot.isChrome || $axscreenshot.isChromiumEdge;


    //-----------------------------------------------------------------------------------
    // Internal Utility
    //-----------------------------------------------------------------------------------

    /**
     * Binds the img area select tool to the specified img (should be the screenshot)
     * 
     * @param {Image to bind the crop tool to} $img 
     **/
    function addCropTool($img) {
        cropTool = $img.axImgAreaSelect({
            instance: true,
            handles: false,
            onOuterOverlayShown: function () { screenshotOverlayVisible(false); },
            onSelectEnd: function () {
                doCrop();
                $axscreenshot.removeAll();
            },
            onSelectCancel: function () { $axscreenshot.removeAll(); }
        });
    };

    /**
     * 
     * @param {} asSelector 
     * @returns {} 
     **/
    function getFeedbackContainers(asSelector) {
        if (asSelector) {
            var $result = [];
            $.each(feedbackContainerClasses, function (index, value) {
                $result.add('.' + value);
            });

            return $result;
        }

        var result = "";
        $.each(feedbackContainerClasses, function (index, value) {
            result += "." + value;

            if (index !== feedbackContainerClasses.length - 1) {
                result += ", ";
            }
        });

        return result;
    };

    /**
     * 
     * 
     * @param {} arr1 
     * @param {} arr2 
     * @returns {} 
     **/
    function existsInArr(arr1, arr2) {
        return arr2.some(function (e) {
            return arr1.indexOf(e) > -1;
        });
    }

    /**
     * 
     * 
     * @param {} str 
     * @param {} arr 
     * @returns {} 
     **/
    function existsInStr(str, arr) {
        var result = false;
        $.each(arr, function (index, value) {
            if (str.indexOf(value) > -1) {
                result = true;
            }
        });

        return result;
    }

    // Get positioning and dimensions of target panel
    function determineTargetPanelDimensions() {
        var zIndex = parseInt($targetPanel.css('z-index'));
        if (isNaN(zIndex)) { zIndex = 0 };
        var x = parseInt($targetPanel.css('left'));
        if (isNaN(x)) x = $('#sitemapHost').is(':visible') ? parseInt($('#sitemapHost').css('width')) : 0;

        return {
            zIndex: zIndex,
            startX: x,
            startY: $('#topPanel').length ? parseInt($('#topPanel').css('height')) : 0,
            width: parseInt($targetPanel.css('width')),
            height: parseInt($targetPanel.css('height'))
        }
    }

    //-----------------------------------------------------------------------------------
    // Utility
    //-----------------------------------------------------------------------------------

    /**
     * Show spinner in textboxes that have a camera icon
     * 
     * @param {Turn off/on the spinner} isSpinning 
     **/
    $axscreenshot.toggleTextBoxScreenshotSpinner = function (isSpinning) {
        if (isSpinning) {
            $('.cameraIcon').prop('disabled', true);
            $('.cameraIcon').addClass('cameraSpinnerIcon');
        } else {
            $('')
            $('.cameraIcon').prop('disabled', false);
            $('.cameraIcon').removeClass('cameraSpinnerIcon');
        }
    };

    /**
     * Remove any screenshot related tools and panels
     **/
    $axscreenshot.removeAll = function () {
        if (cropTool) {
            cropTool.remove();
        }

        $currFeedbackEntry = null;
        $currFeedbackEntry_keyboard = null;

        $('.blackoutOverlay').remove();
        $('#screenshotImg').remove();
        $('#screenshotPanel').remove();
        $('#previewPanel').remove();

        // Calls the post screenshot crop callback that was set during the call to take a screenshot.
        // This callback should perform all functions outside of the screenshot plugin that was defined to be 
        // performed after a crop is performed or if the screenshot was canceled.
        if (postScreenshotCallback != null) {
            postScreenshotCallback();
            postScreenshotCallback = null;
        }
    };

    /**
     * If current prototype is a file url, perform request to load extension
     **/
    $axscreenshot.loadExtensionIfFileUrl = function () {
        if (window.location.origin === "file://" || window.location.origin == "null") {
            window.postMessage(axureCheckResponse, '*');
        }
    }

    /**
     * Checks if the browser and page is set up correctly to take screenshots
     * 
     * @param {Container where the error message would be shown} $target 
     **/
    $axscreenshot.checkIfShowScreenshotBrowserMsg = function ($target, failCondition) {
        if ($axscreenshot.isScreenshotCompatible || failCondition) { return; }

        // Create if empty
        if ($target.html() === "" && !$('#browserMsg').length) {
            var browserMsg = document.createElement('div');
            browserMsg.setAttribute('id', 'browserMsg');
            browserMsg.innerHTML = "To capture images, please use Google Chrome";

            $target.append(browserMsg);
        } else {
            // Else Delete
            $('#browserMsg').remove();
        }
    };

    /**
     * Stores the element that the extension should listen to the keyboard shortcut is pressed. 
     * This is used to reference which issue/comment should get the screenshot
     **/
    $axscreenshot.setKeyboardListener = function ($element) {
        $currFeedbackEntry_keyboard = $element;
    }

    /**
     * Sets up event handlers for screenshot related activities and initializes tool.
     **/
    $axscreenshot.init = function ($targetP, $parentC, $clearOnClickObjects, fbContainers, iContainers, cContainers) {
        // Store jQuery objects representing important elements
        $targetPanel = $targetP;
        $parentContainer = $parentC;
        $clearOnClickObjs = $clearOnClickObjects;
        feedbackContainerClasses = fbContainers;
        issueContainers = iContainers;
        commentContainers = cContainers;

        // Window listeners for screenshot events
        if ($axscreenshot.isScreenshotCompatible) {
            window.addEventListener('message', function (event) {
                var isFileUrl = window.location.origin === "file://" || window.location.origin == "null";

                if ((event.origin === window.location.origin && !isFileUrl) || isFileUrl) {
                    // Listen to screenshot results
                    if (isRequestingScreenshot && typeof event.data === 'object' && event.data !== null && event.data.dataUrl) {
                        isRequestingScreenshot = false;
                        appendScreenshot(event.data.dataUrl);
                    }

                    // Listens to Keyboard request to take screenshot
                    if (event.data === axureShouldTakeScreenshot && isExtensionAttached) {

                        // Listens to Keyboard request to take screenshot
                        // Restore default if values were hidden
                        if ($currFeedbackEntry_keyboard == null || !$currFeedbackEntry_keyboard.is(':visible')) {
                            $currFeedbackEntry_keyboard = $('.issueFeedbackEntryTextAreaContainer');
                        }

                        $currFeedbackEntry_keyboard.parent().find('.cameraIcon').click();
                    }


                    // Extracted functionality to continue setup of extension
                    function attachExtension() {
                        // Legacy: Should work since the extension is the one asking if the page is axure. aka the extension already exists
                        isExtensionAttached = true;
                        isScreenshotSetup = false;

                        if (isFileUrl) {
                            window.postMessage(axureCheckResponse, '*');
                        } else {
                            window.postMessage(axureCheckResponse, window.location.origin);
                        }
                    };
                    // Respond to attach extension
                    if (event.data === axureCheck) {
                        // With firefox, the $('#feedbackHost') doesn't exist yet due to syncing issues with loading js
                        // So if the problem is present, attempt to wait for the requested items to be present before continuing
                        if ($('#feedbackHost').length === 0) {
                            var attempts = 0;

                            function verifyFeedbackLoadedAndAttach() {
                                if ($('#feedbackHost').length === 0 && attempts++ < 10) {
                                    setTimeout(verifyFeedbackLoadedAndAttach, 50);
                                    return;
                                } else {
                                    attachExtension();
                                }
                            };
                        } else {
                            attachExtension();
                        }
                    }


                    // Response to "yesIAmAxure" confirms that both the extension exists and the page was able to communicate with the extension
                    // Mainly used for local files aka fileURLS since they work a bit different from regular pages
                    if (event.data === axureCheckResponseAgain) {
                        isExtensionAttached = true;
                        isScreenshotSetup = false;
                    }
                }
                event.stopPropagation();
                event.preventDefault();
            }, false);

            window.addEventListener('scroll', function (event) {
                $axscreenshot.toggleTextBoxScreenshotSpinner(false);
                isRequestingScreenshot = false;
                $axscreenshot.removeAll();
            }, false);

            window.addEventListener('resize', function (event) {
                $axscreenshot.toggleTextBoxScreenshotSpinner(false);
                isRequestingScreenshot = false;
                $axscreenshot.removeAll();
            }, false);

            var count = 0;
            var numRetries = 5;
            (function NotifyExtension() {
                if (isScreenshotSetup == true && count++ < numRetries) {
                    window.postMessage(axureCheckFor9, window.location.origin);
                    setTimeout(NotifyExtension, 500);
                }
            })();
        }

        // Escape key event handler
        $(document).keyup(function (e) {
            if (e.keyCode === 27) {      // esc key
                //e.stopPropagation();

                $axscreenshot.toggleTextBoxScreenshotSpinner(false);
                isRequestingScreenshot = false;
                $axscreenshot.removeAll();
            }
        });

        // Set state when page has finished loading 
        // And removes the screenshot/preview panel if page is resized
        // TODO: Remove dependancies on feedback page
        function windowLoaded() {
            window.loaded = true;
            $currFeedbackEntry_keyboard = $('#addTopicInput');

            // Listener: Removes screenshot/preview panel if present
            $('.splitbar').mousedown(function () {
                if ($('#screenshotPanel').length || $('#previewPanel').length) {
                    $axscreenshot.toggleTextBoxScreenshotSpinner(false);
                    isRequestingScreenshot = false;
                    $axscreenshot.removeAll();
                }
            });

            $("#sitemapHost, #rsplitbar, #topPanel").mousedown(function () {
                if ($('#missingExtensionDialog').length) {
                    $('#missingExtensionDialog').axDialog('hide');
                }
            });

            $("#sitemapHost, #topPanel, a[pluginid='sitemapHost'], a[pluginid='pageNotesHost'], #interfaceControlFrameMinimizeButton").click(function () {
                $axscreenshot.toggleTextBoxScreenshotSpinner(false);
                isRequestingScreenshot = false;
                $axscreenshot.removeAll();
            });
        };

        $(window).on("load", function () {
            windowLoaded();
        });
        if (!window.loaded && document.readyState === 'complete') {
            windowLoaded();
        }
    };

    /**
     * Lightweight init for mainly only using the preview component
     **/
    $axscreenshot.previewOnlyInit = function ($container) {
        // Variable state setup
        $clearOnClickObjs = $container;

        // Window listeners
        window.addEventListener('scroll', function (event) {
            $axscreenshot.removeAll();
        }, false);
        window.addEventListener('resize', function (event) {
            $axscreenshot.removeAll();
        }, false);

        // Escape key event handler
        $(document).keyup(function (e) {
            if (e.keyCode === 27) {      // esc key
                //e.stopPropagation();

                $axscreenshot.removeAll();
            }
        });

    };

    //-----------------------------------------------------------------------------------
    // Screenshot Section
    //-----------------------------------------------------------------------------------

    /**
     * Checks if the extension has been connected to the browser. If not present, the callback
     * will be performed which is dictated by the controller
     **/
    function checkPlugin(source, noPluginCallback) {
        if (!isExtensionAttached) {
            isRequestingScreenshot = false;
            $axscreenshot.toggleTextBoxScreenshotSpinner(false);

            noPluginCallback(source);

            return false;
        }

        return true;
    };

    /**
     * Posts a message to the window for whatever extension or add-on to take a screenshot
     **/
    function requestScreenshot() {
        if ($axscreenshot.isScreenshotCompatible) {
            if (window.location.origin === "file://" || window.location.origin === "null") {
                window.postMessage(axureTakeScreenshot, '*');
            } else {
                window.postMessage(axureTakeScreenshot, window.location.origin);
            }
        }
    };

    /**
     * Will use dataUrl of screenshot and append it to the page where the user will then select the area of interest
     * 
     * @param {The dataUrl of the screenshot made from browser extension/add-on} dataUrl 
     */
    function appendScreenshot(dataUrl) {
        // targetPanel dimensions
        var dimensions = determineTargetPanelDimensions();
        var zIndex = dimensions.zIndex;
        var x = dimensions.startX;
        var y = dimensions.startY;
        var width = dimensions.width;
        var height = dimensions.height;

        // Crop and resize browser screenshot
        var tempCanvas = document.createElement('canvas');
        tempCanvas.setAttribute('class', 'tempCanvas');
        tempCanvas.setAttribute('width', width);
        tempCanvas.setAttribute('height', height);
        var tempContext = tempCanvas.getContext('2d');
        var tempImage = new Image();

        // Adds screenshot overlay container
        screenshotAddPanel();

        tempImage.onload = function () {
            // Crop image to obtain only right panel
            tempContext.drawImage(this, x, y, width, height, 0, 0, width, height);

            // Append screenshot over rightPanel of page
            var screenshot = document.createElement('img');
            screenshot.setAttribute('id', 'screenshotImg');
            screenshot.setAttribute('class', 'screenshotOverlay');
            screenshot.setAttribute('src', tempCanvas.toDataURL());
            screenshot.setAttribute('width', width);
            screenshot.setAttribute('height', height);
            screenshot.style.zIndex = zIndex + 1;
            screenshot.style.left = x.toString() + 'px';
            $('#screenshotPanel').append(screenshot);

            // Append crop tool
            addCropTool($('#screenshotImg'));

            // TODO: Add listener to container for resizing?

            // Adds screenshot overlay img
            screenshotAddOverlay(screenshot.style.zIndex + 1);
            screenshotOverlayVisible(true);

            // Workaround for temporary cleaning up 
            $('.axScreenshotCanvas').remove();

            // Stop Spinner
            $axscreenshot.toggleTextBoxScreenshotSpinner(false);
        }
        tempImage.src = dataUrl;
    };

    /**
     * Performs the crop of the screenshot and the logic to build a thumbnail img as well as preparing the img for storage
     **/
    function doCrop() {
        var bounds = cropTool.getSelection();

        if (bounds.height <= 0 || bounds.width <= 0) return;

        var baseImg = document.getElementById('screenshotImg');

        var cropCanvas = document.createElement('canvas');
        cropCanvas.setAttribute('class', 'tempCropCanvas');
        cropCanvas.setAttribute('hidden', true);
        cropCanvas.setAttribute('width', bounds.width);
        cropCanvas.setAttribute('height', bounds.height);

        var cropContext = cropCanvas.getContext("2d");

        try {
            cropContext.drawImage(baseImg, bounds.x1, bounds.y1, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);

            var resultUrl = cropCanvas.toDataURL("image/png", 1.0);
            var feedbackServiceUrl = (window.AXSHARE_HOST_SECURE_URL || 'https://share.axure.com') + '/issue';
            var tempId = tempCount++;

            // General Screenshot Container - The thumbnail under an issue or comment
            var overallDiv = document.createElement('div');
            overallDiv.setAttribute('class', 'feedbackItem_thumbnail');
            overallDiv.setAttribute('id', 'screenshot_' + tempId);

            // Image Container
            var imgDiv = document.createElement('div');
            imgDiv.setAttribute('class', 'feedbackItem_thumbnailImg');

            // Temporary Thumbnail Image
            var image = document.createElement('img');
            image.setAttribute('src', resultUrl);       // Sets img url here
            image.setAttribute('class', 'tempThumbnailImg');
            image.style.maxWidth = '90%';
            image.style.maxHeight = '120px';
            image.style.display = 'block';
            image.style.margin = '0 auto';

            // Fullsize Image (Hidden, just use to store src for preview)
            var fsImage = document.createElement('img');
            fsImage.setAttribute('class', 'fullsizeImg');
            fsImage.setAttribute('src', resultUrl);

            // Loading State Container
            var loadingDiv = document.createElement('div');
            loadingDiv.setAttribute('class', 'preloadDiv');

            imgDiv.appendChild(image);
            imgDiv.appendChild(fsImage);
            overallDiv.appendChild(imgDiv);
            overallDiv.appendChild(loadingDiv);

            // Appends thumbnail to the correct issue comment
            var feedbackType = "";
            var $feedbackEntryParent = $currFeedbackEntry.parent();

            if (issueContainers.indexOf($feedbackEntryParent.attr('id')) > -1 || existsInArr($feedbackEntryParent.attr('class').split(' '), issueContainers)) {
                // New Issue/Edit Comment
                $currFeedbackEntry.after(overallDiv);
                $(overallDiv).find('.tempThumbnailImg').hide();
                feedbackType = "issue";
            } else if (existsInStr($currFeedbackEntry.attr('id'), commentContainers)) {
                // New Comment/Edit Comment
                $currFeedbackEntry.append(overallDiv);
                $(overallDiv).find('.tempThumbnailImg').hide();
                feedbackType = "comment";
            }

            // Scrolls page down to newly added screenshot
            //$(overallDiv).get(0).scrollIntoView();

            // TODO: Focus on the correct text area
            // Focuses on text element after crop has been made
            //var parent = $(overallDiv).parent();
            //if (parent.attr('id') === 'feedbackHeader') {
            //    parent.find('#addTopicInput').focus();
            //} else {
            //    parent.find('.feedbackEntryTextArea').focus();
            //}
            $(overallDiv).parent().find('.feedbackEntryTextArea').focus();      // On pins, it doesn't get focused because the text area is still hidden. Need to wait for bubble to shown again.

            // Thumbnail Generation
            var fullsizeImg = new Image();
            var thumbnailCanvas = document.createElement('canvas');
            var thumbnailContext = thumbnailCanvas.getContext('2d');

            // When the image is loaded, set the size of the canvas as well as the url to the image
            image.onload = function () {
                var height = $(image).height();
                var width = $(image).width();

                thumbnailCanvas.height = height;
                thumbnailCanvas.width = width;

                fullsizeImg.src = resultUrl;
            };

            // When the fullsized crop has been saved, perform preloading on crop and crop thumbnail
            fullsizeImg.onload = function () {
                thumbnailContext.drawImage(fullsizeImg, 0, 0, fullsizeImg.width, fullsizeImg.height,
                    0, 0, thumbnailCanvas.width, thumbnailCanvas.height);

                var thumbnailUrl = thumbnailCanvas.toDataURL("image/png", 1.0);

                image.setAttribute('class', 'thumbnailImg');
                image.style.maxWidth = '';
                image.style.maxHeight = '';
                image.style.display = '';
                image.style.margin = '';

                //var top = ($(imgDiv).height() - thumbnailCanvas.height) / 2;
                //image.style.top = top + 'px';

                $(image).hide();

                var ajaxData = {
                    image: resultUrl,
                    thumbnail: thumbnailUrl,
                    type: feedbackType
                };

                // Preuploading Images
                $.ajax({
                    type: 'POST',
                    url: feedbackServiceUrl + '/imagepreupload',
                    data: ajaxData,
                    xhrFields: {
                        withCredentials: true,
                    },
                    success: function (data) {
                        if (data.success) {
                            screenshotCompletePreload(tempId, data.id);
                            $axscreenshot.screenshotBindToDiv($(overallDiv));
                            $axscreenshot.bindEditModeToThumbnail($(overallDiv));
                        } else {
                            $(overallDiv).remove();
                        }
                    },
                    dataType: 'json'
                });
            };
        } catch (e) {
            screenshotOverlayVisible(true);
        }
    };

    /**
     * Attaches guid to thumbnails and removes the loading img 
     **/
    function screenshotCompletePreload(tempId, newId) {
        $('#screenshot_' + tempId).attr('id', 'screenshot_' + newId);
        $('#screenshot_' + newId).toggleClass('newScreenshot', true);
        $('#screenshot_' + newId).find('.preloadDiv').remove();
        $('#screenshot_' + newId).find('.thumbnailImg').show();
    };

    /**
     * Appends the screenshot panel (essentially a container) which serves as an overlay to display a copy of the screen
     */
    function screenshotAddPanel() {
        if (!$('#screenshotPanel').length) {
            // targetPanel dimensions
            var dimensions = determineTargetPanelDimensions();
            var zIndex = dimensions.zIndex;
            var x = dimensions.startX;
            var width = dimensions.width;
            var height = dimensions.height;

            // Build screenshot container
            var screenshotPanel = document.createElement('div');
            screenshotPanel.setAttribute('id', 'screenshotPanel');
            screenshotPanel.style.zIndex = zIndex + 1;
            //screenshotPanel.style.left = x.toString() + 'px';
            screenshotPanel.style.width = width.toString() + 'px';
            screenshotPanel.style.height = height.toString() + 'px';

            $parentContainer.append(screenshotPanel);
        }
    };

    /**
     * Adds the semi-transparent overlay for the screenshot panel
     * 
     * @param {} zIndex 
     */
    function screenshotAddOverlay(zIndex) {
        if (!$('#screenshotOverlay').length) {
            // targetPanel dimensions
            var dimensions = determineTargetPanelDimensions();
            var x = dimensions.startX;
            var width = dimensions.width;
            var height = dimensions.height;

            // Build overlay image
            var overlayImg = document.createElement('img');
            overlayImg.setAttribute('id', 'screenshotOverlay');
            overlayImg.setAttribute('class', 'blackoutOverlay');
            overlayImg.setAttribute('width', width.toString() + 'px');
            overlayImg.setAttribute('height', height.toString() + 'px');
            overlayImg.style.zIndex = zIndex;
            overlayImg.style.left = x.toString() + 'px';

            $('#screenshotPanel').append(overlayImg);

            // Build Instructional Div
            var overlayDiv = document.createElement('div');
            overlayDiv.innerHTML = "Click and drag to<br/>capture an image";
            overlayDiv.setAttribute('class', 'blackoutTextOverlay');
            overlayDiv.style.zIndex = zIndex + 1;

            $('#screenshotPanel').append(overlayDiv);
            $('#screenshotPanel').keypress(function (event) {
                if (event.which == 27) {
                    $axscreenshot.removeAll();
                }
            });

            overlayDiv.style.left = (x + (width / 2) - ($(overlayDiv).width() / 2)).toString() + 'px';
            overlayDiv.style.top = (height / 2).toString() + 'px';
        }
    };

    /**
     * Trigger the Semi-Transparent Overlay on or off for the screenshot overlay
     * 
     * @param {Make the screenshot overlay visible or not} bool 
     */
    function screenshotOverlayVisible(bool) {
        if ($('.blackoutOverlay')) {
            if (bool) {
                $('.blackoutOverlay').show();
                $('.blackoutTextOverlay').show();
            } else {
                $('.blackoutOverlay').hide();
                $('.blackoutTextOverlay').hide();
            }
        }
    };

    /**
     * The primary entry point to take a screen capture and allow the user to "grab" a part of the screen as their screenshot.
     **/
    $axscreenshot.takeScreenshot = function (elem, noPluginCallback, preScreenCallback, postScreenCropCallback) {
        if (!window.loaded) { return; }

        // Chrome Bug: If screenshot icon is hit when there is already a screenshot/preview up, it takes a picture
        // of the overlay as well! Just prevent the repeated click.
        if ($('.blackoutOverlay, .blackoutPreviewOverlay').is(':visible')) { return; }

        if (isRequestingScreenshot) { return; }

        isRequestingScreenshot = true;

        $axscreenshot.toggleTextBoxScreenshotSpinner(true);

        // Checks if the plugin is connected or not
        if (isScreenshotSetup) {
            if (!checkPlugin(elem, noPluginCallback)) {
                return;
            }
        }

        // Cleanup Any Old Screenshot
        $axscreenshot.removeAll();

        // Binding callbacks in preparation to perform screen capture and when crop gets taken or screen is removed
        if (preScreenCallback != null) {
            preScreenCallback();
        }
        postScreenshotCallback = postScreenCropCallback;

        // Identify which issue/comment the screenshot is being taken for
        $currFeedbackEntry = $(elem).parents(getFeedbackContainers());

        // Request for screenshot to be taken from plugin. Force a very short pause to ensure all prior calls have been established.
        // So that screenshot doesn't catch any artifacts
        setTimeout(function () {
            requestScreenshot();
        }, 20);
    };

    /**
     * Function used in callback to coreectly position the image
     **/
    $axscreenshot.screenshotFinishLoadingCallback = function ($overallDiv) {
        var $img = $overallDiv.find('.thumbnailImg');

        (function wait() {
            if ($img.is(':visible')) {
                // Image Alignment
                //var top = ($overallDiv.height() - $img.height()) / 2;
                //$img.css('top', top + 'px');

                // Remove Loading Img Div
                $overallDiv.find('.preloadDiv').remove();

                // Image Div Adjustment: Resize div to fit image
                //$overallDiv.find('.feedbackItem_thumbnailImg').css("height", "100%");
            } else {
                setTimeout(wait, 1000);
            }
        })();
    };


    //-----------------------------------------------------------------------------------
    // Preview Section
    //
    // Will generate and append previewPanel, previewOverlay, and previewImg
    //-----------------------------------------------------------------------------------

    /**
     * Appends the preview panel (essentially a container) which serves as an overlay to preview a thumbnail image
     **/
    function previewAddPanel() {
        if (!$('#previewPanel').length) {
            var zIndex, x, y, width, height, $parent;

            if ($targetPanel !== null && $targetPanel.length) {
                // targetPanel dimensions
                var dimensions = determineTargetPanelDimensions();
                zIndex = dimensions.zIndex;
                x = dimensions.startX;
                width = dimensions.width;
                height = dimensions.height;

                // Assign parent to connect to
                $parent = $parentContainer;
            } else {
                // Document dimensions
                zIndex = 200;
                x = 0;
                //y = 0;
                y = $(window).scrollTop();
                width = $(window).width();
                height = $(window).height();

                // Assign parent to connect to
                $parent = $(document.body);
            }

            // Build screenshot container
            var previewPanel = document.createElement('div');
            previewPanel.setAttribute('id', 'previewPanel');
            previewPanel.style.zIndex = zIndex + 1;
            previewPanel.style.left = x.toString() + 'px';
            previewPanel.style.width = width.toString() + 'px';
            previewPanel.style.height = height.toString() + 'px';

            if (y != null) {
                previewPanel.style.top = y.toString() + 'px';
            }

            $parent.append(previewPanel);
        }
    };

    /**
     * Adds the semi transparent overlay for the preview panel
     * 
     * @param {} zIndex 
     **/
    function previewAddOverlay(zIndex) {
        if (!$('#previewOverlay').length) {
            var width, height;

            if ($targetPanel !== null && $targetPanel.length) {
                // targetPanel dimensions
                width = parseInt($targetPanel.css('width'));
                height = parseInt($targetPanel.css('height'));
            } else {
                // Document dimensions
                width = $(window).width();
                height = $(window).height();
            }

            // Build overlay image
            var overlayImg = document.createElement('img');
            overlayImg.setAttribute('id', 'previewOverlay');
            overlayImg.setAttribute('class', 'blackoutPreviewOverlay');
            overlayImg.setAttribute('width', width);
            overlayImg.setAttribute('height', height);
            overlayImg.style.zIndex = zIndex;

            $('#previewPanel').append(overlayImg);
        }
    };

    /**
     * Adds the actual img for the preview panel
     **/
    function previewAddImg() {
        if (!$('.previewImg').length) {
            var previewImg = document.createElement('img');
            previewImg.setAttribute('class', 'previewImg');
            previewImg.style.zIndex = parseInt($('#previewOverlay').css('z-index')) + 1;

            $('#previewPanel').append(previewImg);
        }
    };

    /**
     * Binds ability to preview the thumbnail. Performs all of the html gen and event handling
     * 
     * @param {Source screenshot thumbnail where the event will be bound to on click.} $currentScreenshotDiv 
     **/
    $axscreenshot.screenshotBindToDiv = function ($currentScreenshotDiv) {
        var id = $currentScreenshotDiv.attr('id');

        // Thumbnail Expand (Preview)
        $currentScreenshotDiv.find('.thumbnailImg').click(function () {
            $axscreenshot.removeAll();

            if (!$('#previewPanel').length) {
                previewAddPanel();
            }

            var $previewPanel = $('#previewPanel');
            if (!$('.blackoutOverlay').length) {
                previewAddOverlay(parseInt($previewPanel.css('z-index')) + 1);
            }

            if (!$('.previewImg').length) {
                previewAddImg();

                var loading = document.createElement('div');
                loading.setAttribute('class', 'preloadDiv');
                loading.style.zIndex = 100;

                $('#previewPanel').append(loading);
            }

            var $previewImg = $('.previewImg');
            $previewImg.attr('id', id);

            $previewImg.on("load", function () {
                var containerHeight = parseInt($('#previewPanel').css('height'));
                var containerWidth = parseInt($('#previewPanel').css('width'));
                var imgHeight = parseInt($previewImg.css('height'));
                var imgWidth = parseInt($previewImg.css('width'));
                var top = (containerHeight - imgHeight) / 2;
                var left = (containerWidth - imgWidth) / 2;

                // Image Centering
                $previewImg.css('top', top + 'px');
                $previewImg.css('left', left + 'px');

                // Close Icon
                $('.previewCloseIcon').remove();
                var closeIcon = document.createElement('img');
                closeIcon.setAttribute('class', 'previewCloseIcon');
                //closeIcon.setAttribute('src', '../../images/closeIcon.png');
                closeIcon.setAttribute('src', '/images/icon_delete.png');
                $(closeIcon).css('top', (top - 18) + 'px');
                $(closeIcon).css('left', (left + imgWidth - 18) + 'px');
                $(closeIcon).css('z-index', parseInt($previewImg.css('z-index')) + 1);
                $previewPanel.append(closeIcon);

                $('#previewPanel').find('.preloadDiv').remove();

                // Remove all when icon is clicked
                $(closeIcon).click(function () {
                    $previewPanel.remove();
                });

                // Remove all when panel, tabs, minimize/close, or refresh is hit
                $('#previewPanel').click(function () {
                    $previewPanel.remove();
                });
                $clearOnClickObjs.click(function () {
                    $previewPanel.remove();
                });
            });

            $previewImg.attr('src', $currentScreenshotDiv.find('.fullsizeImg').attr('src'));
        });
    };


    /**
     * Adds and binds the delete icon for the screenshot
     * 
     * @param {} $div 
     **/
    $axscreenshot.bindEditModeToThumbnail = function ($div) {
        // Delete Link Container
        var deleteDiv = document.createElement('div');
        deleteDiv.setAttribute('class', 'feedbackItem_deleteDiv');

        var icon = document.createElement('a');
        icon.setAttribute('class', 'deleteScreenshotLink');
        icon.innerHTML = 'x';
        icon.setAttribute('href', '#');

        deleteDiv.appendChild(icon);
        $div.append(deleteDiv);

        // Delete Icon Alignment
        var $iconDiv = $div.find('.feedbackItem_deleteDiv');
        $iconDiv.css('top', '0px');

        // Div Size Adjustment
        var $img = $div.find('.thumbnailImg');
        $img.parent().css('padding-top', '10px');
        $img.parent().css('padding-bottom', '10px');

        // Delete Icon Action
        $iconDiv.click(function () {
            $div.hide();
        });
    };

    /**
     * Remove the screenshot delete links and readjust screenshot
     * 
     * @param {} $div 
     **/
    $axscreenshot.removeEditModeFromThumbnail = function ($div) {
        $div.show();
        $div.find('.feedbackItem_deleteDiv').remove();
        $div.find('.feedbackItem_thumbnailImg').css('padding-top', '0px');
        $div.find('.feedbackItem_thumbnailImg').css('padding-bottom', '0px');
    };
})()